#include "TMaskPanel.h"


/***************************************************
 * TMaskContainer
 **************************************************/
 
bool TMaskContainer::init(){ 
    return true;
}



void TMaskContainer::beforeDraw()
{
    glEnable(GL_SCISSOR_TEST);
    if(this->getParent()){
        
        CCPoint worldPos=this->getParent()->convertToWorldSpace(ccp(0,0-getContentSize().height));
        CCEGLView::sharedOpenGLView()->setScissorInPoints(
                                                          worldPos.x,
                                                          worldPos.y,
                                                          getContentSize().width,
                                                          getContentSize().height
                                                          );
    }
    
    
} 


void TMaskContainer::afterDraw()
{
    
    glDisable(GL_SCISSOR_TEST);
    
}

void TMaskContainer::visit()
{
	// quick return if not visible
	if (!isVisible())
    {
		return;
    }
    
	kmGLPushMatrix();
	
    //	glPushMatrix();
	
    if (m_pGrid && m_pGrid->isActive())
    {
        m_pGrid->beforeDraw();
        this->transformAncestors();
    }
    
	this->transform();
    this->beforeDraw();
    
	if(m_pChildren)
    {
		ccArray *arrayData = m_pChildren->data;
		unsigned int i=0;
		
		// draw children zOrder < 0
		for( ; i < arrayData->num; i++ )
        {
			CCNode *child =  (CCNode*)arrayData->arr[i];
			if ( child->getZOrder() < 0 )
            {
				child->visit();
			}
            else
            {
				break;
            }
		}
		
		// this draw
		this->draw();
		
		// draw children zOrder >= 0
		for( ; i < arrayData->num; i++ )
        {
			CCNode* child = (CCNode*)arrayData->arr[i];
			child->visit();
		}
        
	}
    else
    {
		this->draw();
    }
    
    this->afterDraw();
	if ( m_pGrid && m_pGrid->isActive())
    {
		m_pGrid->afterDraw(this);
    }
    
	kmGLPopMatrix();
    
}





/***************************************************
 * TMaskPanel
 **************************************************/

TMaskPanel::TMaskPanel(){
    m_pContainer=NULL;
}

bool TMaskPanel::init(){
    if(!TPanel::init()){
        return false;
    }
    
    m_pContainer=TMaskContainer::create();
    m_pContainer->setTag(1);
    CCNode::addChild(m_pContainer,1);
    
    return true;
}


void TMaskPanel::checkVisible(){
    
    int visibleNum=0;
    CCPoint curPos  = m_pContainer->getPosition();
    int startX=   - curPos.x;
    int startY=  - curPos.y;
    
    renderStartTag=0;
    
    for(uint32 i=0;i<gTouchItems->count();i++){
        TPanelItem* item=(TPanelItem*)gTouchItems->objectAtIndex(i);
        
        if(item->getPositionX()+item->getContentSize().width<startX ||
           item->getPositionY()-item->getContentSize().height>startY ||
           item->getPositionX()-item->getContentSize().width>startX+m_pContainer->getContentSize().width ||
           item->getPositionY()+item->getContentSize().height<startY-m_pContainer->getContentSize().height )
        {
            item->setVisible(false);
        }else{
            
            visibleNum++;
            item->setVisible(true);
            
            if(renderStartTag==0){
                renderStartTag=item->getTag();
            }
        }
        
    }
    
    if(renderStartTag==0){
        renderStartTag=1;
    }
    
}

bool TMaskPanel::ccTouchBegan(CCTouch *pTouch, CCEvent *pEvent){
    
    CCNode* parent=this;
    while(parent){
        if(!parent->isVisible() || !parent->isRunning()){
            
            return false;
        }
        parent=parent->getParent();
    }
    
    TPanel::ccTouchBegan(pTouch, pEvent);
    
    CCPoint worldPos=convertToWorldSpace(CCPointZero);
    
    CCPoint touchLocation = pTouch->getLocation();
    
    if(touchLocation.y> worldPos.y
       || touchLocation.y<worldPos.y-m_pContainer->getContentSize().height){
        return false;
    }
    
    if(touchLocation.x> worldPos.x+  m_pContainer->getContentSize().width
       || touchLocation.x<worldPos.x){
        return false;
    }
    
    return true;
}


void  TMaskPanel::calculateRealHeight(int minHeight){
    
    int height=minHeight==0?-m_pContainer->getContentSize().height:-minHeight;
    
    CCObject* obj;
    
    CCARRAY_FOREACH(m_pContainer->getChildren(), obj){
        CCNode* child=(CCNode*)obj;
        
        int realHeight=(child->getPositionY()-child->getContentSize().height);
        if(realHeight <height){
            height=realHeight;
        }
    }
    m_nRealContainerHeight=-height;
    
}


void  TMaskPanel::calculateRealWidth(){
    
    int width=m_pContainer->getContentSize().width;
    
    CCObject* obj;
    
    CCARRAY_FOREACH(m_pContainer->getChildren(), obj){
        CCNode* child=(CCNode*)obj;
        
        if(!child->isRunning() || !child->isVisible()){
            continue;
        }
        int realHeight=child->getPositionX()+child->getContentSize().width;
        
        if(realHeight>width){
            width=realHeight;
        }
    }
    
    m_nRealContainerWidth=width;
}


void TMaskPanel::initWidthConf(rapidxml::xml_node<> * pItem){
    
    if(!pItem) return;
    
    CCSize size=readContainSize(pItem,getParent());
    if(size.width ==-1) size.width=getContentSize().width;
    if(size.height==-1) size.height=getContentSize().height;
    setContentSize(size);
    
    m_pContainer->setContentSize(size);
    parseConf(pItem->first_node());
  
    onCreateComplete();
}


void TMaskPanel::moveToPos(const CCPoint& pos,bool check){
    
    CCPoint targetPos=m_pContainer->getPosition();
    targetPos.y=-pos.y;
    
    if(check){
        
        if(m_nRealContainerHeight-targetPos.y>getContentSize().height){  
            targetPos.y=-getContentSize().height+m_nRealContainerHeight;
        }
    }
    
    
    m_pContainer->setPosition(targetPos);
}

void TMaskPanel::moveToBottom(){
    CCPoint pos=m_pContainer->getPosition();
    
    if(m_nRealContainerHeight<getContentSize().height){
        
        pos.y=0;
    }else{
        
        pos.y=-getContentSize().height+m_nRealContainerHeight+5;
    }
    m_pContainer->setPosition(pos);
    
}
void TMaskPanel::moveToTop(){
    
    m_pContainer->setPosition(CCPointZero);
}

/***************************************************
 * TScrollPanel
 **************************************************/

bool TScrollPanel::init(){
    
    if(!TMaskPanel::init()){
        return false;
    }
     
    m_bIsScroll=true;
    m_nDirection=TScrollV;
    renderStartTag=0;
    isCheckBottom=false;
    return true;
}

void TScrollPanel::moveToTop(){
    TMaskPanel::moveToTop();
    checkVisible();
    
}
void TScrollPanel::moveToBottom(){
    TMaskPanel::moveToBottom();
    checkVisible();
    
}
 

void TScrollPanel::moveToPos(const CCPoint& pos,bool check){
    TMaskPanel::moveToPos(pos,check);
    checkVisible();
}

TScrollPanel* TScrollPanel::create(xml_node<> * pItem){
    TScrollPanel*  ret=TScrollPanel::create();
    ret->initWidthConf(pItem);
    return ret;
}

void TScrollPanel::addChild(CCNode * child){
    m_pContainer->addChild(child);
}


TPanelItem* TScrollPanel::getItemByTag(int tag){
    return (TPanelItem*)m_pContainer->getChildByTag(tag);
}
 


void TScrollPanel::initWidthConf(rapidxml::xml_node<> * pItem){
    
    if(!pItem) return;
    
    CCSize size=readContainSize(pItem,getParent());
    if(size.width ==-1) size.width=getContentSize().width;
    if(size.height==-1) size.height=getContentSize().height;
    setContentSize(size);
    
    m_pContainer->setContentSize(size);
    parseConf(pItem->first_node());
    if(m_nDirection==TScrollH){
        
        calculateRealWidth();
    }else{
       calculateRealHeight(); 
    }
    onCreateComplete();
}


void TScrollPanel::ccTouchMoved(CCTouch *pTouch, CCEvent *pEvent)
{
    
    TPanel::ccTouchMoved(pTouch, pEvent);
    if(m_bIsScroll){
        
        CCPoint touchLocation = pTouch->getLocation();
        CCPoint preLocation  =pTouch->getPreviousLocation();
        CCPoint curPos  = m_pContainer->getPosition();
        CCPoint nextPos ;
        if(m_nDirection==TScrollH){
            
            float nMoveX= touchLocation.x - preLocation.x;
            nextPos = ccp(curPos.x+ nMoveX, curPos.y);
        }else{
            
            float nMoveY = touchLocation.y - preLocation.y;
            nextPos = ccp(curPos.x,(curPos.y + nMoveY));
        }
         
        m_pContainer->setPosition(nextPos);
        checkVisible();
        
    }
    
    
}


void TScrollPanel::onEnter(){
    TMaskPanel::onEnter();
    
    for(int i=gTouchItems->count()-1;i>=0;i--){
        
        TPanel* pNode =  dynamic_cast<TPanel*>(gTouchItems->objectAtIndex(i));
        if(pNode){
            pNode->scrollParent=this;
        }
    }
}

void TScrollPanel::onExit(){
    TMaskPanel::onExit();
    
    for(int i=gTouchItems->count()-1;i>=0;i--){
        
        TPanel* pNode =  dynamic_cast<TPanel*>(gTouchItems->objectAtIndex(i));
        if(pNode){
            pNode->scrollParent=NULL;
        }
    }

}
 

void TScrollPanel::onMoveEnd(){
    checkVisible();
}


void TScrollPanel::ccTouchEnded(CCTouch *pTouch, CCEvent *pEvent)
{
    if(pTouch){ 
        TPanel::ccTouchEnded(pTouch, pEvent);
    }
    CCPoint curPos (m_pContainer->getPosition().x,m_pContainer->getPosition().y);
     
    if(m_nDirection==TScrollH){
        
        int minX=m_pContainer->getContentSize().width-getRealContainerWidth() ;
        
        
        if (curPos.x <minX){
            curPos.x=minX;
        }
        
        if (curPos.x >0){
            curPos.x=0;
        }
        
        
        
    }else{ 
        
      
        
        
        int maxY=getRealContainerHeight()-m_pContainer->getContentSize().height;
        if (curPos.y >maxY ){
            curPos.y=maxY;
        } 
        
        
        if (curPos.y < 0){
            curPos.y=0;
        }
        
        
    }
    
    m_pContainer->stopAllActions();
    CCPoint nowPos=m_pContainer->getPosition();
    m_pContainer->setPosition(curPos);
    checkVisible();
    m_pContainer->setPosition(nowPos);
    
    
    
    
    m_pContainer->runAction(
                            CCSequence::create(
                                               CCEaseExponentialOut::create(CCMoveTo::create(0.3f, curPos)  ),
                                               CCCallFunc::create(this, callfunc_selector(TScrollPanel::onMoveEnd)),
                                               NULL
                                               )
                            );
    
}